import { FlightLogFieldPresenter } from "./flightlog_fields_presenter";

export function UserSettingsDialog(dialog, onLoad, onSave) {
  // Private Variables

  // generate mixer (from Cleanflight Configurator) (note that the mixerConfiguration index starts at 1)
  let mixerList = [
    {
      name: "Tricopter",
      model: "tricopter",
      image: "tri",
      defaultMotorOrder: [0, 1, 2],
      defaultYawOffset: -Math.PI / 2,
    },
    {
      name: "Quad +",
      model: "quad_x",
      image: "quad_p",
      defaultMotorOrder: [1, 3, 2, 0],
      defaultYawOffset: 0,
    },
    {
      name: "Quad X",
      model: "quad_x",
      image: "quad_x",
      defaultMotorOrder: [1, 3, 2, 0],
      defaultYawOffset: Math.PI / 4,
    },
    {
      name: "Bicopter",
      model: "custom",
      image: "bicopter",
      defaultMotorOrder: [0, 1],
      defaultYawOffset: 0,
    },
    {
      name: "Gimbal",
      model: "custom",
      image: "custom",
      defaultMotorOrder: [0, 1, 2],
      defaultYawOffset: 0,
    },
    {
      name: "Y6",
      model: "y6",
      image: "y6",
      defaultMotorOrder: [4, 1, 3, 5, 2, 0],
      defaultYawOffset: 0,
    },
    {
      name: "Hex +",
      model: "hex_plus",
      image: "hex_p",
      defaultMotorOrder: [4, 1, 3, 5, 2, 0],
      defaultYawOffset: 0,
    },
    {
      name: "Flying Wing",
      model: "custom",
      image: "flying_wing",
      defaultMotorOrder: [0],
      defaultYawOffset: 0,
    },
    {
      name: "Y4",
      model: "y4",
      image: "y4",
      defaultMotorOrder: [1, 3, 2, 0],
      defaultYawOffset: Math.PI / 4,
    },
    {
      name: "Hex X",
      model: "hex_x",
      image: "hex_x",
      defaultMotorOrder: [4, 1, 3, 5, 2, 0],
      defaultYawOffset: Math.PI / 6,
    },
    {
      name: "Octo X8",
      model: "custom",
      image: "octo_x8",
      defaultMotorOrder: [5, 1, 4, 0, 7, 3, 6, 2],
      defaultYawOffset: Math.PI / 8,
    },
    {
      name: "Octo Flat +",
      model: "custom",
      image: "octo_flat_p",
      defaultMotorOrder: [5, 1, 4, 0, 7, 3, 6, 2],
      defaultYawOffset: 0,
    },
    {
      name: "Octo Flat X",
      model: "custom",
      image: "octo_flat_x",
      defaultMotorOrder: [5, 1, 4, 0, 7, 3, 6, 2],
      defaultYawOffset: Math.PI / 8,
    },
    {
      name: "Airplane",
      model: "custom",
      image: "airplane",
      defaultMotorOrder: [0],
      defaultYawOffset: 0,
    },
    {
      name: "Heli 120",
      model: "custom",
      image: "custom",
      defaultMotorOrder: [0],
      defaultYawOffset: 0,
    },
    {
      name: "Heli 90",
      model: "custom",
      image: "custom",
      defaultMotorOrder: [0],
      defaultYawOffset: 0,
    },
    {
      name: "V-tail Quad",
      model: "quad_vtail",
      image: "vtail_quad",
      defaultMotorOrder: [1, 3, 2, 0],
      defaultYawOffset: Math.PI / 4,
    },
    {
      name: "Hex H",
      model: "custom",
      image: "custom",
      defaultMotorOrder: [4, 1, 3, 5, 2, 0],
      defaultYawOffset: 0,
    },
    {
      name: "PPM to SERVO",
      model: "custom",
      image: "custom",
      defaultMotorOrder: [0],
      defaultYawOffset: 0,
    },
    {
      name: "Dualcopter",
      model: "custom",
      image: "custom",
      defaultMotorOrder: [0, 1],
      defaultYawOffset: 0,
    },
    {
      name: "Singlecopter",
      model: "custom",
      image: "custom",
      defaultMotorOrder: [0],
      defaultYawOffset: 0,
    },
    {
      name: "A-tail Quad",
      model: "quad_atail",
      image: "atail_quad",
      defaultMotorOrder: [1, 3, 2, 0],
      defaultYawOffset: Math.PI / 4,
    },
    {
      name: "Custom",
      model: "custom",
      image: "custom",
      defaultMotorOrder: [0],
      defaultYawOffset: 0,
    },
    {
      name: "Custom Airplane",
      model: "custom",
      image: "custom",
      defaultMotorOrder: [0],
      defaultYawOffset: 0,
    },
    {
      name: "Custom Tricopter",
      model: "custom",
      image: "custom",
      defaultMotorOrder: [0, 1, 2],
      defaultYawOffset: -Math.PI / 2,
    },
  ];

  // Setup Defaults....

  let defaultSettings = {
    mixerConfiguration: 3, // Default to Quad-X
    customMix: null, // Default to no mixer configuration
    stickMode: 2, // Default to Mode 2
    stickUnits: false, // Show units on stick display?
    stickTrails: false, // Show stick trails?
    stickInvertYaw: false, // Invert yaw in stick display?
    legendUnits: true, // Show units on legend?
    speedUnits: 1, // Default speed mode = m/s
    altitudeUnits: 1, // Default altitude mode = meters
    gapless: false,
    drawCraft: "3D",
    hasCraft: true,
    drawPidTable: true,
    drawSticks: true,
    drawTime: true,
    drawEvents: true,
    drawAnalyser: true, // add an analyser option
    drawWatermark: false, // Show Watermark on display?
    drawLapTimer: false, // Show Laptimer on display?
    drawGradient: false, // Show Gradient on display?
    drawVerticalBar: true, // Show vertical timebar on display?
    graphSmoothOverride: true, // Ability to toggle Smoothing off=normal/ on=force 0%
    graphExpoOverride: true, // Ability to toggle Expo off=normal/ on=force 100%
    graphGridOverride: true, // Ability to toggle Grid off=normal/ on=force disabled
    analyserSampleRate: 2000 /*Hz*/, // the loop time for the log
    analyserHanning: true, // use a hanning window on the analyser sample data
    eraseBackground: true, // Set to false if you want the graph to draw on top of an existing canvas image
    spectrumType: 0, // By default, frequency Spectrum
    overdrawSpectrumType: 0, // By default, show all filters
    psdHeatmapMin: -40,
    psdHeatmapMax: 10,
    craft: {
      left: "15%", // position from left (as a percentage of width)
      top: "48%", // position from top (as a percentage of height)
      size: "40%", // size (as a percentage of width)
    },
    sticks: {
      left: "75%", // position from left (as a percentage of width)
      top: "20%", // position from top (as a percentage of height)
      size: "30%", // size (as a percentage of width)
    },
    analyser: {
      left: "2%", // position from left (as a percentage of width)
      top: "60%", // position from top (as a percentage of height)
      size: "35%", // size (as a percentage of width)
    },
    analyser_legend: {
      left: "88%", // position from left (as a percentage of width)
      top: "7%", // position from top (as a percentage of height)
      width: "10%", // legend width
    },
    map: {
      left: "2%", // position from left (as a percentage of width)
      top: "5%", // position from top (as a percentage of height)
      size: "35%", // size (as a percentage of width)
    },
    watermark: {
      left: "3%", // position from left (as a percentage of width)
      top: "90%", // position from top (as a percentage of height)
      size: "100%", // size (as a percentage of width)
      transparency: "100%", //transparency of watermark image
      logo: null, // No custom logo
    },
    laptimer: {
      left: "5%", // position from left (as a percentage of width)
      top: "50%", // position from top (as a percentage of height)
      transparency: "40%", // transparency of laptimer
    },
  };

  let currentSettings = {};
  let currentLogo = null;

  function saveCustomMix() {
    let customMix;

    if ($(".custom-mixes").is(":checked")) {
      let motorOrder = new Array(
        mixerList[
          currentSettings.mixerConfiguration - 1
        ].defaultMotorOrder.length
      );
      for (let i = 0; i < motorOrder.length; i++) {
        let select_e = $(
          `select.motor_${
            mixerList[currentSettings.mixerConfiguration - 1].defaultMotorOrder[
              i
            ]
          }_`
        );
        motorOrder[i] = select_e.val();
      }
      customMix = {
        motorOrder: motorOrder,
        yawOffset:
          mixerList[currentSettings.mixerConfiguration - 1].defaultYawOffset,
      };
    } else {
      customMix = null;
    }
    return customMix;
  }

  function convertUIToSettings() {
    let settings = $.extend({}, currentSettings, {
      customMix: saveCustomMix(),
      sticks: {
        top: `${$('.stick-mode-group input[name="stick-top"]').val()}%`,
        left: `${$('.stick-mode-group input[name="stick-left"]').val()}%`,
        size: `${$('.stick-mode-group input[name="stick-size"]').val()}%`,
      },
      craft: {
        top: `${$('.craft-settings input[name="craft-top"]').val()}%`,
        left: `${$('.craft-settings input[name="craft-left"]').val()}%`,
        size: `${$('.craft-settings input[name="craft-size"]').val()}%`,
      },
      analyser: {
        top: `${$('.analyser-settings input[name="analyser-top"]').val()}%`,
        left: `${$('.analyser-settings input[name="analyser-left"]').val()}%`,
        size: `${$('.analyser-settings input[name="analyser-size"]').val()}%`,
      },
      analyser_legend: {
        top: `${$('.analyser-settings input[name="analyser-legend-top"]').val()}%`,
        left: `${$('.analyser-settings input[name="analyser-legend-left"]').val()}%`,
        width: `${$('.analyser-settings input[name="analyser-legend-width"]').val()}%`,
      },
      map: {
        top: `${$('.map-settings input[name="map-top"]').val()}%`,
        left: `${$('.map-settings input[name="map-left"]').val()}%`,
        size: `${$('.map-settings input[name="map-size"]').val()}%`,
      },
      watermark: {
        top: `${$('.watermark-settings input[name="watermark-top"]').val()}%`,
        left: `${$('.watermark-settings input[name="watermark-left"]').val()}%`,
        size: `${$('.watermark-settings input[name="watermark-size"]').val()}%`,
        transparency: `${$(
          '.watermark-settings input[name="watermark-transparency"]'
        ).val()}%`,
        logo: currentLogo,
      },
      drawWatermark: $(".watermark").is(":checked"),
      laptimer: {
        top: `${$('.laptimer-settings input[name="laptimer-top"]').val()}%`,
        left: `${$('.laptimer-settings input[name="laptimer-left"]').val()}%`,
        transparency: `${$(
          '.laptimer-settings input[name="laptimer-transparency"]'
        ).val()}%`,
      },
      drawLapTimer: $(".laptimer").is(":checked"),
      drawGradient: $(".gradient").is(":checked"),
      drawVerticalBar: $(".verticalBar").is(":checked"),
    });
    return settings;
  }

  let availableMotors = []; // motors that appear in the log file
  function getAvailableMotors(flightLog) {
    let fieldNames = flightLog.getMainFieldNames();
    availableMotors = [];

    for (i = 0; i < fieldNames.length; i++) {
      let matches = fieldNames[i].match(/^(motor\[[0-9]+\])/);
      if (matches != null) availableMotors.push(fieldNames[i]);
    }
  }

  function renderFieldOption(i, fieldName, selectedName) {
    let option = $("<option></option>")
      .text(FlightLogFieldPresenter.fieldNameToFriendly(fieldName))
      .attr("value", i);

    if (fieldName == selectedName) {
      option.attr("selected", "selected");
    }

    return option;
  }

  function buildAvailableMotors(select_e, selectedName) {
    for (let i = 0; i < availableMotors.length; i++) {
      select_e.append(renderFieldOption(i, availableMotors[i], selectedName));
    }
  }

  function buildMotorList(mixerConfiguration) {
    let motor_list_e = $(".motorList");
    $(motor_list_e).empty(); // clear all the motors
    if (
      mixerList[mixerConfiguration - 1].defaultMotorOrder.length >
      availableMotors.length
    ) {
      var motors_e = $(
        `<tr>` +
          `<td colspan="2">` +
          `<p class="error">` +
          `Error, you have selected a craft type that required more motors than are available in the log; ` +
          `There are only a maximum of ${
            availableMotors.length
          } motors in the log file; the selection you have chosen requires ${
            mixerList[mixerConfiguration - 1].defaultMotorOrder.length
          } motors.` +
          `</p>` +
          `</td>` +
          `</tr>`
      );
      motor_list_e.append(motors_e);
    } else {
      for (
        let i = 0;
        i < mixerList[mixerConfiguration - 1].defaultMotorOrder.length;
        i++
      ) {
        var motors_e = $(
          `<tr>` +
            `<td colspan="2"><label>Motor ${
              i + 1
            }</label><select class="motor_${i}_"><!-- list generated here --></select></td>` +
            `</tr>`
        );
        let select_e = $("select", motors_e);
        if (currentSettings.customMix != null) {
          for (
            let j = 0;
            j < mixerList[mixerConfiguration - 1].defaultMotorOrder.length;
            j++
          ) {
            if (mixerList[mixerConfiguration - 1].defaultMotorOrder[j] == i) {
              buildAvailableMotors(
                select_e,
                `motor[${currentSettings.customMix.motorOrder[j]}]`
              );
              break;
            }
          }
        } else {
          buildAvailableMotors(select_e, `motor[${i}]`);
        }
        motor_list_e.append(motors_e);
      }
    }
  }

  // Initialisation Code ...

  // Setup the mixer list (pretty much cloned from the configurator...)
  let mixer_list_e = $("select.mixerList");
  for (var i = 0; i < mixerList.length; i++) {
    mixer_list_e.append(
      `<option value="${i + 1}">${mixerList[i].name}</option>`
    );
  }

  function mixerListSelection(val) {
    if (val == null) val = 3; // default for invalid values

    currentSettings.mixerConfiguration = val;

    if (val > 0 && val <= mixerList.length) {
      $(".mixerPreview img").attr(
        "src",
        `./images/motor_order/${mixerList[val - 1].image}.svg`
      );
    }

    buildMotorList(val); // rebuild the motor list based upon the current selection
  }

  function stickModeSelection(val) {
    if (val == null) val = 2; // default for invalid values

    currentSettings.stickMode = val;

    if (val > 0 && val <= 5) {
      $(".modePreview img").attr("src", `./images/stick_modes/Mode_${val}.png`);
    }
  }

  // Buttons and Selectors

  $("select.mixerList").change(function () {
    mixerListSelection(parseInt($(this).val()));
  });

  // Handle the mixer custom toggle
  $(".custom-mixes-group").hide();
  $(".custom-mixes").click(function () {
    if ($(this).is(":checked")) {
      $(".custom-mixes-group").show(300);
    } else {
      $(".custom-mixes-group").hide(200);
    }
  });

  $(".watermark").click(function () {
    if ($(this).is(":checked")) {
      $(".watermark-group").show(300);
    } else {
      $(".watermark-group").hide(200);
    }
  });

  $(".laptimer").click(function () {
    if ($(this).is(":checked")) {
      $(".laptimer-group").show(300);
    } else {
      $(".laptimer-group").hide(200);
    }
  });

  $(".user-settings-dialog-save").click(function (e) {
    onSave(convertUIToSettings());
  });

  $("input[type=radio][name=stick-mode]").change(function () {
    stickModeSelection(parseInt($(this).val()));
  });

  $(".stick-units").click(function () {
    currentSettings.stickUnits = $(this).is(":checked");
  });

  $(".stick-trails").click(function () {
    currentSettings.stickTrails = $(this).is(":checked");
  });

  $(".invert-yaw").click(function () {
    currentSettings.stickInvertYaw = $(this).is(":checked");
  });

  $(".analyser-hanning").click(function () {
    currentSettings.analyserHanning = $(this).is(":checked");
  });

  $(".map-trail-altitude-colored").click(function () {
    currentSettings.mapTrailAltitudeColored = $(this).is(":checked");
  });

  $(".legend-units").click(function () {
    currentSettings.legendUnits = $(this).is(":checked");
  });

  $("input[type=radio][name=speed-mode]").change(function () {
    currentSettings.speedUnits = parseInt($(this).val());
  });

  $("input[type=radio][name=altitude-mode]").change(function () {
    currentSettings.altitudeUnits = parseInt($(this).val());
  });

  // Load Custom Logo
  function readURL(input) {
    if (input.files && input.files[0]) {
      let reader = new FileReader();

      reader.onload = function (e) {
        $("#watermark-logo").attr("src", e.target.result);
        currentLogo = e.target.result;
      };

      reader.readAsDataURL(input.files[0]);
    }
  }

  $("#watermark-logo-load").change(function () {
    readURL(this);
  });

  // Initialise the userSettings

  onLoad(defaultSettings);

  // Public variables

  this.resetToDefaults = function () {
    currentSettings = $.extend({}, defaultSettings);
    onSave(currentSettings);
  };

  this.show = function (flightLog, settings) {
    currentSettings = $.extend(
      {},
      defaultSettings,
      currentSettings,
      settings || {}
    );

    getAvailableMotors(flightLog); // Which motors are in the log file ?

    if (currentSettings.customMix == null) {
      // clear the toggle switch
      $(".custom-mixes").prop("checked", false);
      $(".custom-mixes-group").hide(200);
    } else {
      // set the toggle switch
      $(".custom-mixes").prop("checked", true);
      $(".custom-mixes-group").show(300);
    }

    if (currentSettings.stickUnits != null) {
      // set the toggle switch
      $(".stick-units").prop("checked", currentSettings.stickUnits);
    }

    if (currentSettings.stickTrails != null) {
      // set the toggle switch
      $(".stick-trails").prop("checked", currentSettings.stickTrails);
    }

    if (currentSettings.stickInvertYaw != null) {
      // set the toggle switch
      $(".invert-yaw").prop("checked", currentSettings.stickInvertYaw);
    }

    if (currentSettings.analyserHanning != null) {
      // set the toggle switch
      $(".analyser-hanning").prop("checked", currentSettings.analyserHanning);
    }

    if (currentSettings.mapTrailAltitudeColored != null) {
      // set the toggle switch
      $(".map-trail-altitude-colored").prop(
        "checked",
        currentSettings.mapTrailAltitudeColored
      );
    }

    if (currentSettings.legendUnits != null) {
      // set the toggle switch
      $(".legend-units").prop("checked", currentSettings.legendUnits);
    }

    mixerListSelection(currentSettings.mixerConfiguration); // select current mixer configuration
    stickModeSelection(currentSettings.stickMode);

    // setup the stick mode and dropdowns;
    $("select.mixerList").val(currentSettings.mixerConfiguration);
    $('input:radio[name="stick-mode"]')
      .filter(`[value="${currentSettings.stickMode}"]`)
      .attr("checked", true);

    $('input:radio[name="speed-mode"]')
      .filter(`[value="${currentSettings.speedUnits}"]`)
      .attr("checked", true);
    $('input:radio[name="altitude-mode"]')
      .filter(`[value="${currentSettings.altitudeUnits}"]`)
      .attr("checked", true);

    $('.stick-mode-group input[name="stick-top"]').val(
      parseInt(currentSettings.sticks.top)
    );
    $('.stick-mode-group input[name="stick-left"]').val(
      parseInt(currentSettings.sticks.left)
    );
    $('.stick-mode-group input[name="stick-size"]').val(
      parseInt(currentSettings.sticks.size)
    );
    $('.craft-settings input[name="craft-top"]').val(
      parseInt(currentSettings.craft.top)
    );
    $('.craft-settings input[name="craft-left"]').val(
      parseInt(currentSettings.craft.left)
    );
    $('.craft-settings input[name="craft-size"]').val(
      parseInt(currentSettings.craft.size)
    );
    $('.analyser-settings input[name="analyser-top"]').val(
      parseInt(currentSettings.analyser.top)
    );
    $('.analyser-settings input[name="analyser-left"]').val(
      parseInt(currentSettings.analyser.left)
    );
    $('.analyser-settings input[name="analyser-size"]').val(
      parseInt(currentSettings.analyser.size)
    );

    $('.analyser-settings input[name="analyser-legend-top"]').val(
      parseInt(currentSettings.analyser_legend.top),
    );
    $('.analyser-settings input[name="analyser-legend-left"]').val(
      parseInt(currentSettings.analyser_legend.left),
    );
    $('.analyser-settings input[name="analyser-legend-width"]').val(
      parseInt(currentSettings.analyser_legend.width),
    );
    $('.map-settings input[name="map-top"]').val(
      parseInt(currentSettings.map.top)
    );
    $('.map-settings input[name="map-left"]').val(
      parseInt(currentSettings.map.left)
    );
    $('.map-settings input[name="map-size"]').val(
      parseInt(currentSettings.map.size)
    );

    if (currentSettings.drawWatermark != null) {
      // set the toggle switch
      $(".watermark").prop("checked", currentSettings.drawWatermark);
      currentSettings.drawWatermark
        ? $(".watermark-group").show(200)
        : $(".watermark-group").hide(200);
    }

    $('.watermark-settings input[name="watermark-top"]').val(
      parseInt(currentSettings.watermark.top)
    );
    $('.watermark-settings input[name="watermark-left"]').val(
      parseInt(currentSettings.watermark.left)
    );
    $('.watermark-settings input[name="watermark-size"]').val(
      parseInt(currentSettings.watermark.size)
    );
    $('.watermark-settings input[name="watermark-transparency"]').val(
      parseInt(currentSettings.watermark.transparency)
    );

    if (currentSettings.watermark.logo != null) {
      currentLogo = currentSettings.watermark.logo;
      $("#watermark-logo").attr("src", currentLogo);
    } else {
      currentLogo = $("#watermark-logo").attr("src");
    }

    if (currentSettings.drawLapTimer != null) {
      // set the toggle switch
      $(".laptimer").prop("checked", currentSettings.drawLapTimer);
      currentSettings.drawLapTimer
        ? $(".laptimer-group").show(200)
        : $(".laptimer-group").hide(200);
    }

    $('.laptimer-settings input[name="laptimer-top"]').val(
      parseInt(currentSettings.laptimer.top)
    );
    $('.laptimer-settings input[name="laptimer-left"]').val(
      parseInt(currentSettings.laptimer.left)
    );
    $('.laptimer-settings input[name="laptimer-transparency"]').val(
      parseInt(currentSettings.laptimer.transparency)
    );

    if (currentSettings.drawGradient != null) {
      // set the toggle switch
      $(".gradient").prop("checked", currentSettings.drawGradient);
    }

    if (currentSettings.drawVerticalBar != null) {
      // set the toggle switch
      $(".verticalBar").prop("checked", currentSettings.drawVerticalBar);
    }

    dialog.modal("show");
  };
}
